package cn.elead.chaos.sso.core.filter;

import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.alibaba.fastjson.JSON;

import cn.elead.chaos.sso.core.user.LoginUser;
import cn.elead.chaos.sso.core.util.Response;

/**
 * token方式
 * 
 * @author luopeng
 *
 */
public class SsoOauthFilter extends SsoFilter {

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse res = (HttpServletResponse) response;

		// 请求地址
		String servletPath = req.getServletPath();
		// 排除不需要登录访问的地址
		if (excludedPathHandler(req, res, chain, servletPath)) {
			return;
		}
		// 登出处理
		if (logoutPathHandler(req, res, chain, servletPath)) {
			return;
		}
		// code回调
		if (codeCallbackHandler(req, res, chain, servletPath)) {
			return;
		}
		// 获取用户
		if (getUserHandler(req, res, chain, servletPath)) {
			return;
		}
		// 登录处理
		if (loginPathHandler(req, res, chain, servletPath)) {
			return;
		}
		// 已经登录, 继续执行
		chain.doFilter(request, response);
		return;
	}

	/**
	 * 
	 * @param req
	 * @param res
	 * @param chain
	 * @param servletPath
	 * @return
	 * @throws Exception
	 */
	private boolean loginPathHandler(HttpServletRequest request, HttpServletResponse response, FilterChain chain, String servletPath) throws IOException, ServletException {

		boolean isNotDoFilter = true;
		// 校验租户
		String tenant = null;
		if (vaildTenant) {
			tenant = request.getHeader(tenantHeader);
			if (isEmpty(tenantHeader)) {
				println(response, 400, "{\"code\": 400, \"msg\":\"" + tenant + "不能为空\"}");
				return isNotDoFilter;
			}
		}
		// 获取token
		Response<String> resToken = getToken(request, response, false);
		if (isnull(resToken)) {
			println(response, 400, "{\"code\": 400, \"msg\":\"token不能为空\"}");
			return isNotDoFilter;
		}

		int status = resToken.getCode();
		if (status == 200) {
			// 获取用户
			LoginUser user = null;
			Response<String> remoteData = remoteConnect("/redis/user/" + resToken.getData(), "GET");
			if (remoteData.getCode() == 200) {
				user = JSON.parseObject(remoteData.getData(), LoginUser.class);
				user.setToken(resToken.getData());
				user.setTenant(tenant);
			} else if (remoteData.getCode() == 401) {
				println(response, 401, remoteData.getData());
				return isNotDoFilter;
			} else {
				// json msg
				println(response, remoteData.getCode(), remoteData.getData());
				return isNotDoFilter;
			}
			// 成功后置处理
			postProcessAfterLoginSuccess(request, response, chain, user);
		}
		return isNotDoFilter;

	}

	/**
	 * 登出处理
	 * 
	 * @param request
	 * @param response
	 * @param chain
	 * @param servletPath
	 * @return
	 * @throws IOException
	 */
	private boolean logoutPathHandler(HttpServletRequest request, HttpServletResponse response, FilterChain chain, String servletPath) throws IOException {
		boolean isNotDoFilter = false;
		// logout path check
		if (logoutPath != null && logoutPath.trim().length() > 0 && logoutPath.equals(servletPath)) {
			// 获取token
			Response<String> resToken = getTokenByHeaders(request, response);
			if (isnull(resToken)) {
				println(response, 400, "{\"code\": 400, \"msg\":\"token不能为空\"}");
				return true;
			}

			int status = resToken.getCode();
			if (status == 200) {
				Response<String> remoteData = remoteConnect("/redis/logout/" + resToken.getData(), "DELETE");
				if (remoteData.getCode() == 200) {
					// 成功处理器
					if (null != logoutSuccessHandler) {
						logoutSuccessHandler.onLogoutSuccess(request, response);
					}
					println(response, remoteData.getCode(), remoteData.getData());
					isNotDoFilter = true;
				}
			} else {
				println(response, status, resToken.getData());
				return true;
			}
		}
		return isNotDoFilter;
	}

}
